/************** Guangxi *****************/
#pragma once

#include "contest_net.h"
#include <unordered_map>
#include "Grids.h"
#include "contest_coord.h"
#include <iostream>
#include <unordered_set>
#include <vector>
#include <utility>
#include "RoutingBoundary.h"
#include "idm.h"
#include "./Third/SteinerTree2/Solver.hpp"
#include <string>
#include "contest_util.h"

namespace ieda_contest {

class ContestDataManager;

class Route {
public:
    // 构造函数
    Route(ContestDataManager* data_manager);
    ~Route() = default;
    // 路由处理函数
    void processRoute();
    // 1. Net长度计算，并且将长度储存到Datamanager的Netlist中
    void addNetLength();
    // 2. rerouteAll函数
    void rerouteAll();
    // 3. remove net函数
    void removeNet(ContestNet *SingNetPtr);
    // 4. 建立Route net的unorder map，相比vector有更高的查找效率
    std::unordered_map<std::string, ContestNet*> buildNetPointMap();
    // 5. 针对排序后的net，判断是否需要reroute
    bool isReroute(ContestNet *SingNetPtr);
    // 6. 给定一个Gcell的坐标，得到这个Gcell的引用
    SingleGcellInfo& FindCellInMap(int x, int y, int layerID);
    // 7. 获取overflow的Gcell列表
    std::unordered_set<ContestCoord>& get_Overflow_Gcell_List() {return _OverflowGridsList; }
    // 8. 在overflow的Gcell列表中删除一个元素
    void RemoveElementInOverflowGridsList(ContestCoord OverflowCoord) {_OverflowGridsList.erase(OverflowCoord); }
    // 9. 在overflow的Gcell列表中添加一个元素
    void addElementInOverflowGridsList(ContestCoord OverflowCoord) {_OverflowGridsList.emplace(OverflowCoord); }
    // 10. add net函数
    void addNet(ContestNet *SingNetPtr);
    // 11. 获取所有net的当前cost
    long long get_currentCost() {return _currentCost; }
    // 12. 设置所有net的当前cost
    void set_currentCost(long long SingleCost) {_currentCost += SingleCost; }
    // void set_currentCost(int SingleCost) {_currentCost = SingleCost; }
    // 13. 针对Single Net进行布线
    std::pair<std::vector<ContestSegment>, bool> singleNetRoute(ContestNet *SingNetPtr, std::vector<ContestSegment> &OriginRoute);
    // 14. 获取route的type
    enum Type { Via, Horizontal, Vertical };
    Type getType(ContestSegment routingSegment) const {
        if (routingSegment.get_first().get_x() != routingSegment.get_second().get_x())
            return Type::Horizontal;
        if (routingSegment.get_first().get_y() != routingSegment.get_second().get_y())
            return Type::Vertical;
        return Type::Via;
    }
    // 15. 合并多余的布线
    void reduceRouteSegments(std::vector<ContestSegment> &RoutingSegments);
    // 16. 计算单个net上新的布线方案的线长
    long long get_newCost(std::vector<ContestSegment> &RoutingSegment);
    // 17. 初始化所有net的cost，用线长
    void initialCurrentCost();
    // 18. 获取Net Map
    std::unordered_map<std::string, ContestNet*> &getNetMap() {return _net_Map; }
    // 19. SingleNet连接性检查
    bool SingleNetConnectivity(std::vector<ContestPin>& pinList, std::vector<ContestSegment>& segmentList, string netName);
    // 其他可能的方法...

private:
    ContestDataManager* _data_manager = nullptr;  // 指向 DataManager 实例的指针
    std::unordered_map<std::string, ContestNet*> _net_Map;
    std::unordered_set<ContestCoord> _OverflowGridsList;
    long long _currentCost = 0;
};

class RoutingGraphManager {
public:
    RoutingGraphManager(ContestDataManager* data_manager):
                        _data_manager(data_manager) {};
    ~RoutingGraphManager() = default;
    void setBoundaryInfor (RoutingBoundaryInfo* BoundaryInfo) {_BoundaryInfo = BoundaryInfo; }
    std::map<int, idb::IdbLayerDirection>& getLayerDir();
    std::vector<int>& getLayerFactor(int powerFactor); // 不需要这个，powerFactor和LayerFactor是一个东西。
    void createGraph(const std::vector<int>& LayerFactor,
                     const std::map<int, idb::IdbLayerDirection>& layer_idx_to_direction_map);
    void createGraphV2(const std::vector<int>& LayerFactor,
                     const std::map<int, idb::IdbLayerDirection>& layer_idx_to_direction_map);
    steiner_tree::UndirectedGraph<long long> &get_SteinerTree() {return _G; } 
    // void set_SteinerTree(steiner_tree::UndirectedGraph<long long> G) {_G = G; }
    RoutingBoundaryInfo* get_BoundaryInfo() {return _BoundaryInfo; }
    std::vector<ContestSegment> 
    createFinalRoute(const std::vector<size_t> &Eids, const ContestNet *Net);

private:
    // 1. Steiner tree
    steiner_tree::UndirectedGraph<long long> _G;
    // 2. data_manager
    ContestDataManager* _data_manager;
    // 3. Boundary information
    RoutingBoundaryInfo* _BoundaryInfo;
    std::map<int, idb::IdbLayerDirection> _layer_idx_to_direction_map;
    std::vector<int> _LayerFactor;

};

} // namespace ieda_contest